#!/usr/bin/env python3
import socket
import sys
import argparse

from scapy.all import (
    IP,
    UDP,
    Ether,
    Packet,
    bind_layers,
    get_if_hwaddr,
    get_if_list,
    sendp
)
from scapy.fields import *


def get_if():
    ifs=get_if_list()
    iface=None # "h1-eth0"
    for i in get_if_list():
        if "eth0" in i:
            iface=i
            break;
    if not iface:
        print("Cannot find eth0 interface")
        exit(1)
    return iface

class SourceRoute(Packet):
   fields_desc = [ BitField("bos", 0, 1),
                   BitField("port", 0, 15)]

bind_layers(Ether, SourceRoute, type=0x1234)
bind_layers(SourceRoute, SourceRoute, bos=0)
bind_layers(SourceRoute, IP, bos=1)

def main():
    parser = argparse.ArgumentParser(description='Send packets with different forwarding modes')
    parser.add_argument('destination', help='Destination IP address')
    parser.add_argument('--src-route', type=str, help='Space separated port numbers for source routing')
    parser.add_argument('--ip-forward', action='store_true', help='Use IPv4 forwarding mode')

    args = parser.parse_args()

    addr = socket.gethostbyname(args.destination)
    iface = get_if()

    if args.src_route and args.ip_forward:
        print("Error: Cannot use both source routing and IP forwarding modes simultaneously")
        exit(1)

    if not args.src_route and not args.ip_forward:
        print("Please specify either --src-route or --ip-forward")
        exit(1)

    print("sending on interface %s to %s" % (iface, str(addr)))

    if args.src_route:
        # Source Routing Mode
        print("Using Source Routing mode with ports:", args.src_route)
        s = args.src_route
        i = 0
        pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff', type=0x1234)

        ports = s.split(" ")
        for idx, p in enumerate(ports):
            try:
                bos = 1 if idx == len(ports) - 1 else 0
                pkt = pkt / SourceRoute(bos=bos, port=int(p))
                i = i+1
            except ValueError:
                print("Invalid port number:", p)
                exit(1)

        pkt = pkt / IP(dst=addr) / UDP(dport=4321, sport=1234)
        pkt.show2()
        sendp(pkt, iface=iface, verbose=False)
        print("Source routing packet sent!")

    elif args.ip_forward:
        # IPv4 Forwarding Mode
        print("Using IPv4 Forwarding mode")
        pkt = Ether(src=get_if_hwaddr(iface), dst='ff:ff:ff:ff:ff:ff', type=0x800) / \
              IP(dst=addr) / UDP(dport=4321, sport=1234)
        pkt.show2()
        sendp(pkt, iface=iface, verbose=False)
        print("IPv4 packet sent!")

if __name__ == '__main__':
    main()
